package com.example.CarManagement.sys.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.example.CarManagement.common.Result;
import com.example.CarManagement.enumPojo.ApplicationStatus;
import com.example.CarManagement.enumPojo.DriverStatus;
import com.example.CarManagement.exception.ServiceException;
import com.example.CarManagement.sys.dto.WxUserLogin;
import com.example.CarManagement.sys.entity.*;
import com.example.CarManagement.sys.mapper.*;
import com.example.CarManagement.sys.service.impl.RoleServiceImpl;
import com.example.CarManagement.sys.service.impl.SendMessageService;
import com.example.CarManagement.sys.service.impl.UserServiceImpl;
import com.example.CarManagement.sys.vo.CarStatusStatVo;
import com.example.CarManagement.sys.vo.MonthApplyStatVo;
import com.example.CarManagement.sys.vo.VehicleOrderCountVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static net.sf.jsqlparser.util.validation.metadata.NamedObject.user;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author 徐佳彪
 * @since 2025-07-08
 */
@RestController
@RequestMapping("/sys/user")
public class UserController {

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private RoleServiceImpl roleService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ApplicationsMapper applicationsMapper;

    @Autowired
    private CarInfoMapper carInfoMapper;

    @Autowired
    private DriversMapper driversMapper;

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private SendMessageService sendMessageService;


    @PostMapping("/login")
    public Result<?> login(@RequestBody User user) {
        return userService.login(user);
    }


    @PostMapping("/wxLogin")
    public Result<?> wxLogin(@RequestBody WxUserLogin user) {
        return userService.wxLogin(user);
    }


    @GetMapping("/info")
    public Result<?> info(@RequestHeader("Authorization") String token) {
        LoginUser userInfo = userService.getUserInfo(token);
        if (userInfo != null) {
            User user = userInfo.getUser();
            user.setPassword(null);
            Role roleByUserId = roleService.getRoleByUserId(user.getId());
            userInfo.setRole(roleByUserId);
            userInfo.setUser(user);
            return Result.success(userInfo);
        } else {
            throw new ServiceException("401", "用户信息有误，请重新登录");
        }
    }

    @GetMapping("/push/{userId}")
    public void pushMessage(@PathVariable  String userId) {
        sendMessageService.pushMessage(userId, "测试消息");
    }



    @PostMapping("/logout")
    public Result<?> logout(@RequestHeader("Authorization") String token) {

        return userService.logout(token);
    }


    @PutMapping("/updateSelfPass")
    public Result<?> updateSelfPass(@RequestBody User user, @RequestHeader("Authorization") String token) {
        return userService.updateSelfPassword(user, token);
    }

    @PreAuthorize("@se.hasPermi('USER_SELECT')")
    @GetMapping("/updateInfo")
    public Result<?> updateInfo(@RequestHeader("Authorization") String token) {
        LoginUser userInfo = userService.getUserInfo(token);

        User user = userInfo.getUser();
        User byId = userService.getById(user);
        byId.setPassword(null);

        return Result.success(byId);
    }


    @PutMapping("/updateAv")
    public Result<?> updateAv(@RequestBody User user) {
        System.out.println(user.toString());
        return userService.updateAv(user);
    }


    // 首页数据
    @GetMapping("/dashboard")
    public Result<?> getDashboard() {

        // 总申请
        Long allApplicationCount = applicationsMapper.selectCount(null);

        // 已完成
        LambdaQueryWrapper<Applications> completedLambdaQueryWrapper = new LambdaQueryWrapper<>();
        completedLambdaQueryWrapper.eq(Applications::getStatus, ApplicationStatus.completed);
        Long completedCount = applicationsMapper.selectCount(completedLambdaQueryWrapper);

        // 进行中
        LambdaQueryWrapper<Applications> rejectedLambdaQueryWrapper = new LambdaQueryWrapper<>();
        rejectedLambdaQueryWrapper.eq(Applications::getStatus, ApplicationStatus.in_progress);
        Long rejectedCount = applicationsMapper.selectCount(completedLambdaQueryWrapper);

        // 可用车
        LambdaQueryWrapper<CarInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CarInfo::getStatus, 0);
        Long carCount = carInfoMapper.selectCount(wrapper);

        // 可用司机
        LambdaQueryWrapper<Drivers> driversLambdaQueryWrapper = new LambdaQueryWrapper<>();
        driversLambdaQueryWrapper.eq(Drivers::getStatus, DriverStatus.available);
        Long driversCount = driversMapper.selectCount(driversLambdaQueryWrapper);


        // 本月里程（KM）
        LambdaQueryWrapper<Orders> ordersLambdaQueryWrapper = new LambdaQueryWrapper<>();
        ordersLambdaQueryWrapper.eq(Orders::getStatus, ApplicationStatus.completed);
        LocalDate start = LocalDate.now().withDayOfMonth(1);
        LocalDate end = LocalDate.now().withDayOfMonth(LocalDate.now().lengthOfMonth());
        ordersLambdaQueryWrapper.between(Orders::getCreatedAt, start, end);
        List<Orders> ordersList = ordersMapper.selectList(ordersLambdaQueryWrapper);

        // 计算本月完成订单的总里程
        java.math.BigDecimal totalMileage = java.math.BigDecimal.ZERO;
        for (Orders order : ordersList) {
            if (order.getActualMileage() != null) {
                totalMileage = totalMileage.add(order.getActualMileage());
            }
        }


        // 饼图：申请状态分布
        List<Map<String, Object>> statusDist = new ArrayList<>();
        String[] labels = {"审批中", "已批准", "已拒绝", "已完成", "已取消"};
        ApplicationStatus[] statuses = {ApplicationStatus.pending, ApplicationStatus.approved, ApplicationStatus.rejected, ApplicationStatus.completed, ApplicationStatus.cancelled};

        for (int i = 0; i < labels.length; i++) {
            Map<String, Object> item = new HashMap<>();
            item.put("name", labels[i]);
            item.put("value", applicationsMapper.selectCount(Wrappers.<Applications>lambdaQuery().eq(Applications::getStatus, statuses[i])));
            statusDist.add(item);
        }

        // ========== 3. 折线图：月度趋势 ==========
        int year = LocalDate.now().getYear();          // 当前年

        // 1. 申请量按月分组
        List<Map<String, Object>> applyList = applicationsMapper.selectMaps(new QueryWrapper<Applications>().select("DATE_FORMAT(created_at,'%Y-%m') AS month", "COUNT(*) AS applyCount").eq("deleted", 0).apply("YEAR(created_at) = {0}", year).groupBy("month"));

        // 2. 完成量按月分组
        List<Map<String, Object>> completeList = applicationsMapper.selectMaps(new QueryWrapper<Applications>().select("DATE_FORMAT(updated_at,'%Y-%m') AS month", "COUNT(*) AS completeCount").eq("deleted", 0).eq("status", "completed").apply("YEAR(updated_at) = {0}", year).groupBy("month"));

        // 3. 合并结果
        Map<String, MonthApplyStatVo> tmp = new LinkedHashMap<>();
        applyList.forEach(m -> {
            String month = (String) m.get("month");
            tmp.put(month, new MonthApplyStatVo(month, (Long) m.get("applyCount"), 0L));
        });
        completeList.forEach(m -> {
            String month = (String) m.get("month");
            MonthApplyStatVo vo = tmp.computeIfAbsent(month, k -> new MonthApplyStatVo(k, 0L, 0L));
            vo.setCompleteCount((Long) m.get("completeCount"));
        });

        List<MonthApplyStatVo> monthTrend = tmp.values().stream().sorted(Comparator.comparing(MonthApplyStatVo::getMonth)).collect(Collectors.toList());


        // ========== 4. 仪表盘：司机出勤率 ==========
        long totalDrivers = driversMapper.selectCount(null);
        long onDutyDrivers = driversMapper.selectCount(Wrappers.<Drivers>lambdaQuery().eq(Drivers::getStatus, DriverStatus.on_duty));
        int attendanceRate = totalDrivers == 0 ? 0 : (int) Math.round(onDutyDrivers * 100.0 / totalDrivers);
        // ========== 5. 表格：车辆状态 ==========
        // 1. 先查总记录数（排除已删除）
        long total = carInfoMapper.selectCount(new QueryWrapper<CarInfo>().eq("deleted", 0));

        List<CarStatusStatVo> carStatus = null;
        if (total != 0) {   // 防止除 0

            // 按 status 分组查数量
            List<Map<String, Object>> list = carInfoMapper.selectMaps(new QueryWrapper<CarInfo>().select("status AS type", "COUNT(*) AS num").eq("deleted", 0).groupBy("status"));

            // 组装 VO 并计算百分比
            carStatus = list.stream().map(m -> {
                Integer type = (Integer) m.get("type");
                Long num = (Long) m.get("num");
                BigDecimal percent = BigDecimal.valueOf(num * 100.0 / total).setScale(2, RoundingMode.HALF_UP);
                return new CarStatusStatVo(type, num, percent);
            }).collect(Collectors.toList());
        }


        // ========== 6. 表格：司机本月之星 ==========
        // 构造查询条件
        QueryWrapper<Orders> vehicleWrapper = new QueryWrapper<>();
        vehicleWrapper.select("driver_id", "COUNT(*) AS order_number").eq("deleted", 0)          // 软删除过滤
                .groupBy("driver_id").orderByDesc("order_number").last("LIMIT 3");          // MySQL 取前 3

        List<Map<String, Object>> maps = ordersMapper.selectMaps(vehicleWrapper);
        List<VehicleOrderCountVo> topDrivers = maps.stream().map(m -> new VehicleOrderCountVo((String) m.get("driver_id"),                    // 字符串直接强转
                        ((Number) m.get("order_number")).longValue()))   // 先 Number 再取 long
                .collect(Collectors.toList());

        List<VehicleOrderCountVo> endTopDrivers = new ArrayList<>();
        topDrivers.forEach(vehicleOrderCountVo -> {
            LambdaQueryWrapper<Drivers> driversLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            driversLambdaQueryWrapper1.eq(Drivers::getDriverId, vehicleOrderCountVo.getDriverId());
            Drivers drivers = driversMapper.selectOne(driversLambdaQueryWrapper1);
            try {
                vehicleOrderCountVo.setDriverName(userMapper.selectById(drivers.getUserId()).getUsername());
                endTopDrivers.add(vehicleOrderCountVo);
            } catch (Exception e) {
                System.out.println("过滤不需要司机订单");
            }
        });


        // 最外层 Map
        Map<String, Object> datas = new HashMap<>();

        // 6 个指标卡片
        List<Map<String, Object>> cardData = new ArrayList<>();
        Map<String, Integer> cards = new HashMap<>();
        cards.put("总申请", Math.toIntExact(allApplicationCount));
        cards.put("已完成", Math.toIntExact(completedCount));
        cards.put("在途中", Math.toIntExact(rejectedCount));
        cards.put("可用车", Math.toIntExact(carCount));
        cards.put("可用司机", Math.toIntExact(driversCount));
        cards.put("本月里程(km)", Math.toIntExact(totalMileage.intValue()));

        for (Map.Entry<String, Integer> entry : cards.entrySet()) {
            Map<String, Object> card = new HashMap<>();
            card.put("title", entry.getKey());
            card.put("value", entry.getValue());
            cardData.add(card);
        }

        datas.put("cards", cardData);
        datas.put("statusDist", statusDist);
        datas.put("monthTrend", monthTrend);
        datas.put("attendanceRate", attendanceRate);
        datas.put("carStatus", carStatus);
        datas.put("topDrivers", endTopDrivers);

        return Result.success(datas);
    }


    @PreAuthorize("@se.hasPermi('USER_UPDATE_PASSWORD')")
    @PostMapping("/updatePassword")
    public Result<?> updatePassword(@RequestBody User user, @RequestHeader("Authorization") String token) {
        return userService.updatePassword(user, token);
    }


    @PreAuthorize("@se.hasPermi('USER_INSERT')")
    @PostMapping("/register")
    public Result<?> register(@RequestBody User user) {
        return userService.register(user);
    }

    @PreAuthorize("@se.hasPermi('USER_SELECT')")
    @GetMapping("/getUserOperations")
    public Result<?> getUserOperations() {
        return userService.getUserOperations();
    }


    @PreAuthorize("@se.hasPermi('USER_SELECT')")
    @GetMapping("/getUserList")
    public Result<?> getUserList(@RequestParam Map<String, Object> searchModel, @RequestHeader("Authorization") String token) {

        return userService.getUserList(searchModel, token);

    }

    @PreAuthorize("@se.hasPermi('USER_UPDATE')")
    @GetMapping("/{id}")
    public Result<?> getUserById(@PathVariable String id) {
        return Result.success(userService.getById(id));
    }


    @PreAuthorize("@se.hasPermi('USER_DELETE')")
    @DeleteMapping("/{id}")
    public Result<?> deleteById(@PathVariable String id) {
        return Result.success(userService.removeById(id));
    }


    @PreAuthorize("@se.hasPermi('USER_UPDATE')")
    @PostMapping("/update")
    public Result<?> update(@RequestBody User user) {
        return userService.updateUser(user);
    }


    /**
     * 设置用户权限
     *
     * @param
     * @return
     */
    @PreAuthorize("@se.hasPermi('USER_UPDATE')")
    @PostMapping("/setUserRole")
    public Result<?> setUserRole(@RequestBody UserRole userRole) {
        return userService.setUserRole(userRole);
    }

    @PreAuthorize("@se.hasPermi('USER_UPDATE')")
    @GetMapping("/getUserRole/{id}")
    public Result<?> getUserRole(@PathVariable String id) {
        return userService.getUserRole(id);
    }
}
